/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package AlgebraLinear.SistemaLinear;

import java.util.*;

/**
 *
 * @author Andre
 */
public class EquacaoAdmin {

    //Uma LISTA para armazenar todas as Strings de Equações
    private List<String> equacoes = new ArrayList <String>();
    //Uma LISTA para armazenar as Strings de variaveis para saida
    private List<String> variaveis = new ArrayList <String>();
    //Matriz e um Vetor para os dados dos calculos
    private Double[][] matriz;
    private double[] independente;
    //Instância do Objeto que fará os calculos
    private EliminacaoGauss gauss =  new EliminacaoGauss();

    //Este método é somente para adicionar as Equacões a Classe
    public void AdicionarEquacao(String equacao){
        if(equacao != null && !equacao.equals("") && equacao.split("=").length == 2){
            this.equacoes.add(equacao);
        }else{
            throw new IllegalArgumentException(equacao+" não pode ser adicionada");
        }//Encerra if/else
    }//Encerra o método

    public boolean AdicionarEquacao(String[] equacao){
        for(int i = 0; i < equacao.length; i++){
            this.AdicionarEquacao(equacao[i]);
        }//Encerra for
        return true;
    }//Encerra o método

    public String Caulcula(){
        if(this.equacoes.size() == 0){
            return "Você não adicionou nenhuma Equação";
        }
        //Inicialmente organizo os Dados das Equacões
        this.organizarDados();

        double[] resultados;
        //Mando realizar os calculos com os dados

        resultados = this.gauss.Caucular(matriz, independente);

        //Instancio uma String de saida, para ser preenchida com o resultado
        String saida = "";
        for(int i = 0; i< resultados.length; i++){
            saida += this.variaveis.get(i) + " = " + ( (resultados[i] == -0.0)?0.0:resultados[i] ) +"\n";
        }

        this.limpaCalculos();
        return saida;
    }

    private void organizarDados(){
        String[] ind = new String[equacoes.size()];
        String[][] coeficiente = new String[equacoes.size()][equacoes.size()];

        for(int i = 0; i < equacoes.size(); i++){
            //Lasso para preencher o vetor de identidade
            ind[i] = this.equacoes.get(i).split("=")[1];

            //Lasso para preencher a matriz de coeficientes
            String[] eq = equacoes.get(i).split("[=]")[0].split("[A-z]");
            for (int j = 0; j < eq.length; j++) {
                if (eq[j].replaceAll("[+]", "").equals("")) {
                    coeficiente[i][j] = "1.0";
                } else if (eq[j].replaceAll("[+]", "").equals("-")) {
                    coeficiente[i][j] = "-1.0";
                } else {
                    coeficiente[i][j] = eq[j].replaceAll("[+]", "");
                }//fecho o if/else
            }//Fecho o lasso for j
        }//Fecho o Lasso for i
        this.setMatriz(coeficiente);
        this.setIndependente(ind);
        this.addVariaveis();
    }//Fecho o método

    private void setMatriz(String equa[][]){
        matriz = new Double[equa.length][equa.length];
        //Lasso para o preenchimento da Matriz matriz
        for(int i = 0; i < equa.length; i++){
            for(int j = 0; j< equa[i].length; j++){
                matriz[i][j] = Double.parseDouble(equa[i][j]);
            }
        }
    }

    private void setIndependente(String num[]){
        independente = new double[num.length];
        for(int i = 0; i < independente.length; i++){
            independente[i] = Double.parseDouble(num[i]);
        }
    }

    public void addVariaveis(){
        //Adiciono as variaveis da primeira linha
        String[]  var = this.equacoes.get(0).split("=")[0].replaceAll("[0-9]", "").split("[+-]");
        for(int i = 0; i < var.length; i++){
            this.variaveis.add(var[i]);
        }
        if( !verificaVariaveis() ){
                throw new IllegalArgumentException("As variaveis informadas são diferentes");
        }//fecho if
    }//fecho o método

    //Algum erro de logica ocorre nessa verificação
    public boolean verificaVariaveis(){
        for(String eq : this.equacoes){
            String[] var = eq.split("=")[0].replaceAll("[0-9]", "").split("[+-]");
            for (int i = 0; i < var.length; i++) {
                if ( !var[i].equalsIgnoreCase(this.variaveis.get(i)) ) {
                    return false;
                }//Fecho o if
            }//Fecho o for i
        }//Fecho o foreach
        return true;
    }

    public void limpaCalculos(){
        this.variaveis.clear();
        this.equacoes.clear();
    }

    public int equacoesAdicionadas(){
        return this.equacoes.size();
    }
}
